﻿using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Xml;
using DiscoveryLogic.Common.Utilities;
using DiscoveryLogic.DataViz.NetworkDiagram.NetworkData;

namespace DiscoveryLogic.DataViz.NetworkDiagram
{
    /// <summary>
    /// 
    /// </summary>
    [Serializable]
    public class Edge
    {
        #region props
        private Guid _ID;
        /// <summary></summary>
        public Guid ID
        {
            get
            {
                return this._ID;
            }
            set
            {
                this._ID = value;
            }
        }

        private string _Label;
        /// <summary></summary>
        public string Label
        {
            get
            {
                return this._Label;
            }
            set
            {
                this._Label = value;
            }
        }

        private Guid _VerticeID1;
        /// <summary></summary>
        public Guid VerticeID1
        {
            get
            {
                return this._VerticeID1;
            }
            set
            {
                this._VerticeID1 = value;
            }
        }

        private Guid _VerticeID2;
        /// <summary></summary>
        public Guid VerticeID2
        {
            get
            {
                return this._VerticeID2;
            }
            set
            {
                this._VerticeID2 = value;
            }
        }

        private float _Thickness;
        /// <summary></summary>
        public float Thickness
        {
            get
            {
                return this._Thickness;
            }
            set
            {
                this._Thickness = value;
            }
        }

        private EdgeLineStyle _LineStyle;
        /// <summary></summary>
        public EdgeLineStyle LineStyle
        {
            get
            {
                return this._LineStyle;
            }
            set
            {
                this._LineStyle = value;
            }
        }

        private float _Length;
        /// <summary></summary>
        public float Length
        {
            get
            {
                return this._Length;
            }
            set
            {
                this._Length = value;
            }
        }

        private Color _PenColor;
        /// <summary></summary>
        public Color PenColor
        {
            get
            {
                return this._PenColor;
            }
            set
            {
                this._PenColor = value;
            }
        }

        private LinkDataObject _Tag;
        /// <summary></summary>
        public LinkDataObject Tag
        {
            get
            {
                return this._Tag;
            }
            set
            {
                this._Tag = value;
            }
        }

        private string _Tooltip;
        /// <summary></summary>
        public string Tooltip
        {
            get
            {
                return this._Tooltip;
            }
            set
            {
                this._Tooltip = value;
            }
        }

        private bool _FixedLength;
        /// <summary></summary>
        public bool FixedLength
        {
            get
            {
                return this._FixedLength;
            }
            set
            {
                this._FixedLength = value;
            }
        }
        #endregion

        #region ctor
        /// <summary>
        /// 
        /// </summary>
        public Edge()
        {
            this._ID = Guid.NewGuid();
            this._Label = string.Empty;
            this._VerticeID1 = Guid.Empty;
            this._VerticeID2 = Guid.Empty;
            this._Thickness = 2;
            this._LineStyle = EdgeLineStyle.Solid;
            this._Length = 100;
            this._PenColor = Color.FromArgb(100, Color.Brown);
            this._Tag = null;
            this._Tooltip = string.Empty;
            this._FixedLength = false;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="id"></param>
        /// <param name="label"></param>
        /// <param name="length"></param>
        /// <param name="vID1"></param>
        /// <param name="vID2"></param>
        public Edge(Guid id, string label,float length, 
            Guid vID1, Guid vID2)
        {
            this._ID = id;
            this._Label = label;
            this._Length = length;
            this._VerticeID1 = vID1;
            this._VerticeID2 = vID2;
            this._Thickness = 2;
            this._LineStyle = EdgeLineStyle.Solid;
        	this._PenColor = Color.FromArgb(100, Color.Brown);
            this._Tag = null;
            this._Tooltip = label;
            this._FixedLength = false;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="id"></param>
        /// <param name="label"></param>
        /// <param name="length"></param>
        /// <param name="vID1"></param>
        /// <param name="vID2"></param>
        /// <param name="tag"></param>
        public Edge(Guid id, string label, float length, 
            Guid vID1, Guid vID2, LinkDataObject tag)
            : this(id, label, length, vID1, vID2)
        {
            this._Tag = tag;
        }
        #endregion

        #region xml 
        /// <summary>
        /// 
        /// </summary>
        /// <param name="xDoc"></param>
        /// <param name="eNode"></param>
        public void Save(ref XmlDocument xDoc, XmlNode eNode)
        {
            PropertyInfo[] props = this.GetType().GetProperties();
            foreach (PropertyInfo prop in props)
            {
                object propValue = prop.GetValue(this, null);
                if (propValue != null)
                {
                    XmlDataUtil.UpdateAttribute(ref xDoc, eNode, prop.Name, propValue.ToString());
                }
            }
            if(this.Tag !=null)
                this.Tag.Save(ref xDoc, eNode);
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="eNode"></param>
        /// <returns></returns>
        public Edge Read(XmlNode eNode)
        {
            Edge e = (Edge)Activator.CreateInstance(this.GetType());
            PropertyInfo[] props = this.GetType().GetProperties();
            foreach (PropertyInfo prop in props)
            {
                if (eNode.Attributes.GetNamedItem(prop.Name) != null)
                {
                    string propValue = XmlDataUtil.GetAttributeValue(eNode, prop.Name, "");
                    SimpleDataType dataType = SimpleDataTypeUtil.ToSimpleDataType(prop.PropertyType);
                    object propValue2 = SimpleDataTypeUtil.ToDbValue(dataType, propValue.ToString());
                    if (propValue2 != null && propValue2 != DBNull.Value)
                    prop.SetValue(e, propValue2, null);
                }
            }
            e.Tag=new LinkDataObject();
            e.Tag = e.Tag.Read(eNode);
            return e;
        }
        #endregion

        /// <summary>
        /// 
        /// </summary>
        /// <returns></returns>
        public Edge Clone()
        {
            Edge e=new Edge();
            PropertyInfo[] props = this.GetType().GetProperties();
            foreach (PropertyInfo prop in props)
            {
                object propVal = prop.GetValue(this, null);
                prop.SetValue(e,propVal,null);
            }
            return e;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="v"></param>
        /// <returns></returns>
        public bool Contains(Vertice v)
        {
            if(this.VerticeID1==v.ID || this.VerticeID2==v.ID)
                return true;
            else
                return false;
        }
    }
}
